home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 112 / EnigmaAmiga112CD.iso / dalla rivista / news / orbit / source / planet.c < prev    next >
C/C++ Source or Header  |  2000-05-01  |  24KB  |  979 lines

  1. /*
  2.     Amiga port by Oliver Gantert
  3.  
  4.     27.04.2000 - fixed some compiler warnings
  5. */
  6. /*
  7.  
  8. ORBIT, a freeware space combat simulator
  9. Copyright (C) 1999  Steve Belczyk <steve1@genesis.nred.ma.us>
  10.  
  11. This program is free software; you can redistribute it and/or
  12. modify it under the terms of the GNU General Public License
  13. as published by the Free Software Foundation; either version 2
  14. of the License, or (at your option) any later version.
  15.  
  16. This program is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. GNU General Public License for more details.
  20.  
  21. You should have received a copy of the GNU General Public License
  22. along with this program; if not, write to the Free Software
  23. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  24.  
  25. */
  26.  
  27. #include "orbit.h"
  28.  
  29. static float MaterialColor[] = {
  30.   1.0, 1.0, 1.0, 1.0}
  31. static float specular[] = {
  32.   0.0, 0.0, 0.0, 1.0}
  33. static float emission[] = {
  34.   0.0, 0.0, 0.0, 1.0}
  35. ;
  36.  
  37. void DrawPlanets()
  38. /*
  39.  *  Draw all the planets
  40.  */
  41. {
  42.   int p;
  43.  
  44.   /* Draw orbits */ 
  45.   if (draw_orbits) DrawOrbits(); 
  46.   
  47.   for (p=0; p<NPLANETS; p++)
  48.   {
  49.     if (!planet[p].hidden) DrawPlanet (p);
  50.   }
  51. }
  52.  
  53. void DrawPlanet (int p)
  54. /*
  55.  *  Draw the pretty planet
  56.  */
  57. {
  58.   double th, r2, v[3];
  59.   int pr;
  60.  
  61.   /* Set color to white, will be modulated with texture */
  62.   if (textures)
  63.   {
  64.     glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialColor);
  65.     glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, MaterialColor);
  66.   }
  67.   else
  68.   {
  69.     glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, planet[p].color);
  70.     glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, planet[p].color);
  71.   }
  72.   
  73.   glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular); 
  74.   glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, emission); 
  75.   glMaterialf  (GL_FRONT_AND_BACK, GL_SHININESS, 0.0); 
  76.  
  77.   glPushMatrix();
  78.  
  79.   /* How far away from view is this planet? */
  80.   Vsub (v, planet[p].pos, player.pos);
  81.   planet[p].absrange2 = Mag2(v);
  82.   planet[p].range2 = r2 = planet[p].absrange2 / planet[p].radius2;
  83.  
  84.   /* Translate to where the planet is */
  85.   Vsub (v, planet[p].pos, player.pos);
  86.   glTranslated (v[0], v[1], v[2]);
  87.   th = fmod (absT, 120.0);
  88.   th = 360.0*th / 120.0;
  89.  
  90.   /* Don't bother with oblicity or rotation if it's just a point */
  91.   if (r2 < 200.0*200.0)
  92.   {
  93.     /* Planet oblicity */
  94.     glRotated (planet[p].oblicity, 1.0, 0.0, 0.0);
  95.  
  96.     /* Moons get their primary's oblicity as well */
  97.     if (planet[p].is_moon)
  98.     {
  99.       pr = planet[p].primary;
  100.       glRotated (planet[pr].oblicity, 1.0, 0.0, 0.0);
  101.     }
  102.   }
  103.  
  104.   glPushMatrix();  /* Save un-rotated matrix */
  105.  
  106.   /* Planet rotation */
  107.   if (r2 < 200.0*200.0) glRotated (th, 0.0, 0.0, 1.0);
  108.  
  109.   if (r2 < 5.0 * 5.0)
  110.   {
  111.     if (textures) glEnable (GL_TEXTURE_2D);
  112.     glBindTexture (GL_TEXTURE_2D, planet[p].texid);
  113.     glCallList (planet[p].list320);
  114.   }
  115.   else if (r2 < 25.0 * 25.0)
  116.   {
  117.     if (textures) glEnable (GL_TEXTURE_2D);
  118.     glBindTexture (GL_TEXTURE_2D, planet[p].texid);
  119.     glCallList (planet[p].list80);
  120.   }
  121.   else if (r2 < 200.0 * 200.0)
  122.   {
  123.     if (textures) glEnable (GL_TEXTURE_2D);
  124.     glBindTexture (GL_TEXTURE_2D, planet[p].texid);
  125.     glCallList (planet[p].list20);
  126.   }
  127.   else if (r2 < (5000.0 * 5000.0))
  128.   {
  129.     glDisable (GL_TEXTURE_2D);
  130.     glDisable (GL_LIGHTING);
  131.     glPointSize (2.0);
  132.     glBegin (GL_POINTS);
  133.     glColor3fv (planet[p].color);
  134.     glVertex3d (0.0, 0.0, 0.0);
  135.     glEnd();
  136.   }
  137.   else if (r2 < (50000.0 * 50000.0))
  138.   {
  139.     glDisable (GL_TEXTURE_2D);
  140.     glDisable (GL_LIGHTING);
  141.     glPointSize (1.0);
  142.     glBegin (GL_POINTS);
  143.     glColor3fv (planet[p].color);
  144.     glVertex3d (0.0, 0.0, 0.0);
  145.     glEnd();
  146.   }
  147.  
  148.   glDisable (GL_TEXTURE_2D);
  149.   glEnable (GL_LIGHTING);
  150.  
  151.   /* Pop rotate matrix */
  152.   glPopMatrix();
  153.  
  154.   glPopMatrix();
  155. }
  156.  
  157. void MakePlanetLists()
  158. /*
  159.  *  Define planet display lists
  160.  */
  161. {
  162.   int p;
  163.  
  164.   for (p=0; p<NPLANETS; p++)
  165.   {
  166.     /* Sun is special */
  167.     if (p == 0)
  168.     {
  169.       MakeSunList();
  170.     }
  171.     else
  172.     {
  173.       MakePlanetList (p);
  174.     }
  175.   }
  176.  
  177.   /* Make orbit lists */
  178.   MakeOrbitLists();
  179. }
  180.  
  181. void MakePlanetList (int p)
  182. /*
  183.  *  Make planet lists for planet p
  184.  */
  185. {
  186.   /* We make three different versions of the planet for display at various
  187.     distances */
  188.   if (glIsList (planet[p].list20)) glDeleteLists (planet[p].list20, 1);
  189.   planet[p].list20 = glGenLists (1);
  190.  
  191.   glNewList (planet[p].list20, GL_COMPILE);
  192.   maxtdiff = 0.47;
  193.   Sphere (planet[p].radius, stacks0, slices0);
  194.   glEndList();
  195.  
  196.   if (glIsList (planet[p].list80)) glDeleteLists (planet[p].list80, 1);
  197.   planet[p].list80 = glGenLists (1);
  198.  
  199.   glNewList (planet[p].list80, GL_COMPILE);
  200.   maxtdiff = 0.609384;
  201.   Sphere (planet[p].radius, stacks1, slices1);
  202.   glEndList();
  203.  
  204.   if (glIsList (planet[p].list320)) glDeleteLists (planet[p].list320, 1);
  205.   planet[p].list320 = glGenLists (1);
  206.  
  207.   glNewList (planet[p].list320, GL_COMPILE);
  208.   maxtdiff = 0.414069;
  209.   Sphere (planet[p].radius, stacks2, slices2);
  210.   glEndList();
  211. }
  212.  
  213. void MakeSunList()
  214. /*
  215.  *  Make Sol's display list
  216.  */
  217. {
  218.   if (glIsList (planet[0].list20)) glDeleteLists (planet[0].list20, 1);
  219.   planet[0].list20 = glGenLists (1);
  220.  
  221.   glNewList (planet[0].list20, GL_COMPILE);
  222.   glDisable (GL_LIGHTING);
  223.   glDisable (GL_TEXTURE_2D);
  224.   glColor3d (0.8, 0.8, 0.6);
  225.   Sphere (planet[0].radius, stacks0, slices0);
  226.   glEnable (GL_TEXTURE_2D);
  227.   glEnable (GL_LIGHTING);
  228.   glEndList();
  229.  
  230.   if (glIsList (planet[0].list80)) glDeleteLists (planet[0].list80, 1);
  231.   planet[0].list80 = glGenLists (1);
  232.  
  233.   glNewList (planet[0].list80, GL_COMPILE);
  234.   glDisable (GL_LIGHTING);
  235.   glDisable (GL_TEXTURE_2D);
  236.   glColor3d (0.8, 0.8, 0.6);
  237.   Sphere (planet[0].radius, stacks1, slices1);
  238.   glEnable (GL_TEXTURE_2D);
  239.   glEnable (GL_LIGHTING);
  240.   glEndList();
  241.  
  242.   if (glIsList (planet[0].list320)) glDeleteLists (planet[0].list320, 1);
  243.   planet[0].list320 = glGenLists (1);
  244.  
  245.   glNewList (planet[0].list320, GL_COMPILE);
  246.   glDisable (GL_LIGHTING);
  247.   glDisable (GL_TEXTURE_2D);
  248.   glColor3d (0.8, 0.8, 0.6);
  249.   Sphere (planet[0].radius, stacks2, slices2);
  250.   glEnable (GL_TEXTURE_2D);
  251.   glEnable (GL_LIGHTING);
  252.   glEndList();
  253. }
  254.  
  255. void ReadPlanetTexture (int p)
  256. /*
  257.  *  Read in the planet's texture
  258.  */
  259. {
  260.   FILE *fd;
  261.   int x, y, c, i;
  262.   char fn[64];
  263.  
  264.   /* Sun is special */
  265.   if (p == 0)
  266.   {
  267.     planet[p].color[0] = planet[p].color[1] = planet[p].color[2] = 1.0;
  268.     return;
  269.   }
  270.  
  271.   /* Zero planet average color */
  272.   planet[p].color[0] = planet[p].color[1] = planet[p].color[2] = 0.0;
  273.  
  274.   /* Get id for this texture */
  275.   if (planet[p].texid == (-1)) glGenTextures (1, &planet[p].texid);
  276.   glBindTexture (GL_TEXTURE_2D, planet[p].texid);
  277.  
  278.   glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
  279.  
  280.   /* Put up a progress message */
  281.   Mprint ("Reading %s", planet[p].texfname);
  282.   Log ("ReadPlanetTexture: Reading texture file %s", planet[p].texfname);
  283.   DrawSplash();
  284.  
  285.   /* Open file */
  286.   sprintf (fn, "maps/%s", planet[p].texfname);
  287.   if (NULL == (fd = fopen (fn, "rb")))
  288.   {
  289.     Log ("ReadPlanetTexture: Can't open %s", planet[p].texfname);
  290.     FinishSound();
  291.     CloseLog();
  292.     exit (0);
  293.   }
  294.  
  295.   /* Read past PPM header */
  296.   while (10 != fgetc(fd));
  297.   while (10 != fgetc(fd));
  298.   while (10 != fgetc(fd));
  299.  
  300.   /* Read in the color data */
  301.   for (y=0; y<256; y++)
  302.   {
  303.     for (x=0; x<256; x++)
  304.     {
  305.       for (i=0; i<3; i++)
  306.       {
  307.         c = fgetc (fd);
  308.         if ( (c < 0) || (c > 255) )
  309.         {
  310.           Log ("ReadPlanetTexture: Error reading texture file %s", planet[p].texfname);
  311.           Log ("ReadPlanetTexture: x,y,i,c; %d %d %d %d", x, y, i, c);
  312.           FinishSound();
  313.           CloseLog();
  314.           exit (0);
  315.         }
  316.  
  317.         planet[p].tex[255-y][x][i] = 0xff & c;
  318.         planet[p].color[i] += (float) c;
  319.       }
  320.     }
  321.   }
  322.  
  323.   /* Compute average color */
  324.   for (i=0; i<3; i++) planet[p].color[i] /= (256.0 * 256.0 * 256.0);
  325.  
  326.   /* Set the texture */
  327.   glTexImage2D (GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, planet[p].tex);
  328.   glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  329.   glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  330.   glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  331.   glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  332.   glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  333.  
  334.   fclose (fd);
  335. }
  336.  
  337. void InitPlanets()
  338. /*
  339.  *  All sorts of planet initialization
  340.  */
  341. {
  342.   int p;
  343.  
  344.   for (p=0; p<NPLANETS; p++)
  345.   {
  346.     planet[p].custom = 1;
  347.     planet[p].texid = (-1);
  348.     planet[p].orbitlist = (-1);
  349.   }
  350.  
  351.   /* Randomize theta for each planet */
  352.   RandomPlanets();
  353.  
  354.   /* Reset planets */
  355.   ResetPlanets();
  356. }
  357.  
  358. void ResetPlanets()
  359. /*
  360.  *  Set planets back to the way they should be at start
  361.  */
  362. {
  363.   int p;
  364.  
  365.   p = 0;
  366.  
  367.   Log ("ResetPlanets: resetting planets");
  368.  
  369.   strcpy (planet[p].name, "Sol");
  370.   strcpy (planet[p].texfname, "sol.ppm");
  371.   planet[p].radius = 696000.000000 / KM_TO_UNITS1;
  372.   planet[p].dist = 0.000000 / KM_TO_UNITS2;
  373.   planet[p].is_moon = 0;
  374.   planet[p].primary = 0;
  375.   planet[p].oblicity = 0.0;
  376.   planet[p].angvel = 0.0;
  377.   p++;
  378.  
  379.   strcpy (planet[p].name, "Mercury");
  380.   strcpy (planet[p].texfname, "mercury.ppm");
  381.   planet[p].radius = 2440.000000 / KM_TO_UNITS1;
  382.   planet[p].dist = (realdistances ? 50.79 : 05.7900002) / KM_TO_UNITS2;
  383.   planet[p].is_moon = 0;
  384.   planet[p].primary = 0;
  385.   planet[p].angvel = 0.004166 / 87.969;
  386.   p++;
  387.  
  388.   strcpy (planet[p].name, "Venus");
  389.   strcpy (planet[p].texfname, "venus.ppm");
  390.   planet[p].radius = 6052.000000 / KM_TO_UNITS1;
  391.   planet[p].dist = (realdistances ? 108.2 : 10.8199997) / KM_TO_UNITS2;
  392.   planet[p].is_moon = 0;
  393.   planet[p].primary = 0;
  394.   planet[p].oblicity = 177.3;
  395.   planet[p].angvel = 0.004166 / 224.7;
  396.   p++;
  397.  
  398.   strcpy (planet[p].name, "Earth");
  399.   strcpy (planet[p].texfname, "earth.ppm");
  400.   planet[p].radius = 6371.000000 / KM_TO_UNITS1;
  401.   planet[p].dist = (realdistances ? 149.6 : 14.9600006) / KM_TO_UNITS2;
  402.   planet[p].is_moon = 0;
  403.   planet[p].primary = 0;
  404.   planet[p].oblicity = 23.45;
  405.   planet[p].angvel = 0.004166 / 365.256;
  406.   p++;
  407.  
  408.   strcpy (planet[p].name, "Moon");
  409.   strcpy (planet[p].texfname, "moon.ppm");
  410.   planet[p].radius = 1737.500000 / KM_TO_UNITS1;
  411.   planet[p].dist = 0.384400 / KM_TO_UNITS2;
  412.   planet[p].is_moon = 1;
  413.   planet[p].primary = 3;
  414.   planet[p].oblicity = 0.0;
  415.   planet[p].angvel = 0.004166 / 27.3;
  416.   p++;
  417.  
  418.   strcpy (planet[p].name, "Mars");
  419.   strcpy (planet[p].texfname, "mars.ppm");
  420.   planet[p].radius = 3390.000000 / KM_TO_UNITS1;
  421.   planet[p].dist = (realdistances ? 227.9 : 22.7899994) / KM_TO_UNITS2;
  422.   planet[p].is_moon = 0;
  423.   planet[p].primary = 0;
  424.   planet[p].oblicity = 25.19;
  425.   planet[p].angvel = 0.004166 / 686.98;
  426.   p++;
  427.  
  428.   strcpy (planet[p].name, "Phobos");
  429.   strcpy (planet[p].texfname, "phobos.ppm");
  430.   planet[p].radius = 13.000000 / KM_TO_UNITS1;
  431.   planet[p].dist = 0.009380 / KM_TO_UNITS2;
  432.   planet[p].is_moon = 1;
  433.   planet[p].primary = 5;
  434.   planet[p].oblicity = 0.0;
  435.   planet[p].angvel = 0.004166 / 0.319;
  436.   p++;
  437.  
  438.   strcpy (planet[p].name, "Deimos");
  439.   strcpy (planet[p].texfname, "deimos.ppm");
  440.   planet[p].radius = 8.000000 / KM_TO_UNITS1;
  441.   planet[p].dist = 0.022340 / KM_TO_UNITS2;
  442.   planet[p].is_moon = 1;
  443.   planet[p].primary = 5;
  444.   planet[p].oblicity = 0.0;
  445.   planet[p].angvel = 0.004166 / 1.262;
  446.   p++;
  447.  
  448.   strcpy (planet[p].name, "Jupiter");
  449.   strcpy (planet[p].texfname, "jupiter.ppm");
  450.   planet[p].radius = 69911.000000 / KM_TO_UNITS1;
  451.   /* planet[p].dist = 77.8400024 / KM_TO_UNITS2; */
  452.   planet[p].dist = (realdistances ? 778.4 : 50.0) / KM_TO_UNITS2;
  453.   planet[p].is_moon = 0;
  454.   planet[p].primary = 0;
  455.   planet[p].oblicity = 3.12;
  456.   planet[p].angvel = 0.004166 / 4332.0;
  457.   p++;
  458.  
  459.   strcpy (planet[p].name, "Io");
  460.   strcpy (planet[p].texfname, "io.ppm");
  461.   planet[p].radius = 1821.000000 / KM_TO_UNITS1;
  462.   planet[p].dist = 0.421000 / KM_TO_UNITS2;
  463.   planet[p].is_moon = 1;
  464.   planet[p].primary = 8;
  465.   planet[p].oblicity = 0.0;
  466.   planet[p].angvel = 0.004166 / 1.769;
  467.   p++;
  468.  
  469.   strcpy (planet[p].name, "Europa");
  470.   strcpy (planet[p].texfname, "europa.ppm");
  471.   planet[p].radius = 1565.000000 / KM_TO_UNITS1;
  472.   planet[p].dist = 0.671000 / KM_TO_UNITS2;
  473.   planet[p].is_moon = 1;
  474.   planet[p].primary = 8;
  475.   planet[p].oblicity = 0.0;
  476.   planet[p].angvel = 0.004166 / 3.552;
  477.   p++;
  478.  
  479.   strcpy (planet[p].name, "Ganymede");
  480.   strcpy (planet[p].texfname, "ganymede.ppm");
  481.   planet[p].radius = 2634.000000 / KM_TO_UNITS1;
  482.   planet[p].dist = 1.070000 / KM_TO_UNITS2;
  483.   planet[p].is_moon = 1;
  484.   planet[p].primary = 8;
  485.   planet[p].oblicity = 0.0;
  486.   planet[p].angvel = 0.004166 / 7.155;
  487.   p++;
  488.  
  489.   strcpy (planet[p].name, "Callisto");
  490.   strcpy (planet[p].texfname, "callisto.ppm");
  491.   planet[p].radius = 2403.000000 / KM_TO_UNITS1;
  492.   planet[p].dist = 1.883000 / KM_TO_UNITS2;
  493.   planet[p].is_moon = 1;
  494.   planet[p].primary = 8;
  495.   planet[p].oblicity = 0.0;
  496.   planet[p].angvel = 0.004166 / 16.69;
  497.   p++;
  498.  
  499.   strcpy (planet[p].name, "Saturn");
  500.   strcpy (planet[p].texfname, "saturn.ppm");
  501.   planet[p].radius = 58232.000000 / KM_TO_UNITS1;
  502.   /* planet[p].dist = 142.7000000 / KM_TO_UNITS2; */
  503.   planet[p].dist = (realdistances ? 1427.0 : 75.0) / KM_TO_UNITS2;
  504.   planet[p].is_moon = 0;
  505.   planet[p].primary = 0;
  506.   planet[p].oblicity = 26.73;
  507.   planet[p].angvel = 0.004166 / 10759.0;
  508.   p++;
  509.  
  510.   strcpy (planet[p].name, "Mimas");
  511.   strcpy (planet[p].texfname, "mimas.ppm");
  512.   planet[p].radius = 198.800003 / KM_TO_UNITS1;
  513.   planet[p].dist = 0.185000 / KM_TO_UNITS2;
  514.   planet[p].is_moon = 1;
  515.   planet[p].primary = 13;
  516.   planet[p].oblicity = 0.0;
  517.   planet[p].angvel = 0.004166 / 0.942;
  518.   p++;
  519.  
  520.   strcpy (planet[p].name, "Enceladus");
  521.   strcpy (planet[p].texfname, "enceladus.ppm");
  522.   planet[p].radius = 249.100006 / KM_TO_UNITS1;
  523.   planet[p].dist = 0.238000 / KM_TO_UNITS2;
  524.   planet[p].is_moon = 1;
  525.   planet[p].primary = 13;
  526.   planet[p].oblicity = 0.0;
  527.   planet[p].angvel = 0.004166 / 1.37;
  528.   p++;
  529.  
  530.   strcpy (planet[p].name, "Tethys");
  531.   strcpy (planet[p].texfname, "tethys.ppm");
  532.   planet[p].radius = 529.900024 / KM_TO_UNITS1;
  533.   planet[p].dist = 0.294000 / KM_TO_UNITS2;
  534.   planet[p].is_moon = 1;
  535.   planet[p].primary = 13;
  536.   planet[p].oblicity = 0.0;
  537.   planet[p].angvel = 0.004166 / 1.888;
  538.   p++;
  539.  
  540.   strcpy (planet[p].name, "Dione");
  541.   strcpy (planet[p].texfname, "dione.ppm");
  542.   planet[p].radius = 560.000000 / KM_TO_UNITS1;
  543.   planet[p].dist = 0.377000 / KM_TO_UNITS2;
  544.   planet[p].is_moon = 1;
  545.   planet[p].primary = 13;
  546.   planet[p].oblicity = 0.0;
  547.   planet[p].angvel = 0.004166 / 2.737;
  548.   p++;
  549.  
  550.   strcpy (planet[p].name, "Rhea");
  551.   strcpy (planet[p].texfname, "rhea.ppm");
  552.   planet[p].radius = 764.000000 / KM_TO_UNITS1;
  553.   planet[p].dist = 0.527000 / KM_TO_UNITS2;
  554.   planet[p].is_moon = 1;
  555.   planet[p].primary = 13;
  556.   planet[p].oblicity = 0.0;
  557.   planet[p].angvel = 0.004166 / 4.518;
  558.   p++;
  559.  
  560.   strcpy (planet[p].name, "Titan");
  561.   strcpy (planet[p].texfname, "titan.ppm");
  562.   planet[p].radius = 2575.000000 / KM_TO_UNITS1;
  563.   planet[p].dist = 1.221000 / KM_TO_UNITS2;
  564.   planet[p].is_moon = 1;
  565.   planet[p].primary = 13;
  566.   planet[p].oblicity = 0.0;
  567.   planet[p].angvel = 0.004166 / 15.9;
  568.   p++;
  569.  
  570.   strcpy (planet[p].name, "Iapetus");
  571.   strcpy (planet[p].texfname, "iapetus.ppm");
  572.   planet[p].radius = 718.000000 / KM_TO_UNITS1;
  573.   planet[p].dist = 3.561000 / KM_TO_UNITS2;
  574.   planet[p].is_moon = 1;
  575.   planet[p].primary = 13;
  576.   planet[p].oblicity = 0.0;
  577.   planet[p].angvel = 0.004166 / 79.33;
  578.   p++;
  579.  
  580.   strcpy (planet[p].name, "Uranus");
  581.   strcpy (planet[p].texfname, "uranus.ppm");
  582.   planet[p].radius = 25362.000000 / KM_TO_UNITS1;
  583.   /* planet[p].dist = 287.1000000 / KM_TO_UNITS2; */
  584.   planet[p].dist = (realdistances ? 2871.0 : 100.0) / KM_TO_UNITS2;
  585.   planet[p].is_moon = 0;
  586.   planet[p].primary = 0;
  587.   planet[p].oblicity = 97.86;
  588.   planet[p].angvel = 0.004166 / 30685.0;
  589.   p++;
  590.  
  591.   strcpy (planet[p].name, "Miranda");
  592.   strcpy (planet[p].texfname, "miranda.ppm");
  593.   planet[p].radius = 235.000000 / KM_TO_UNITS1;
  594.   planet[p].dist = 0.130000 / KM_TO_UNITS2;
  595.   planet[p].is_moon = 1;
  596.   planet[p].primary = 21;
  597.   planet[p].oblicity = 0.0;
  598.   planet[p].angvel = 0.004166 / 1.413;
  599.   p++;
  600.  
  601.   strcpy (planet[p].name, "Ariel");
  602.   strcpy (planet[p].texfname, "ariel.ppm");
  603.   planet[p].radius = 580.000000 / KM_TO_UNITS1;
  604.   planet[p].dist = 0.191000 / KM_TO_UNITS2;
  605.   planet[p].is_moon = 1;
  606.   planet[p].primary = 21;
  607.   planet[p].oblicity = 0.0;
  608.   planet[p].angvel = 0.004166 / 2.52;
  609.   p++;
  610.  
  611.   strcpy (planet[p].name, "Umbriel");
  612.   strcpy (planet[p].texfname, "umbriel.ppm");
  613.   planet[p].radius = 585.000000 / KM_TO_UNITS1;
  614.   planet[p].dist = 0.266000 / KM_TO_UNITS2;
  615.   planet[p].is_moon = 1;
  616.   planet[p].primary = 21;
  617.   planet[p].oblicity = 0.0;
  618.   planet[p].angvel = 0.004166 / 4.144;
  619.   p++;
  620.  
  621.   strcpy (planet[p].name, "Titania");
  622.   strcpy (planet[p].texfname, "titania.ppm");
  623.   planet[p].radius = 789.000000 / KM_TO_UNITS1;
  624.   planet[p].dist = 0.436000 / KM_TO_UNITS2;
  625.   planet[p].is_moon = 1;
  626.   planet[p].primary = 21;
  627.   planet[p].oblicity = 0.0;
  628.   planet[p].angvel = 0.004166 / 8.706;
  629.   p++;
  630.  
  631.   strcpy (planet[p].name, "Oberon");
  632.   strcpy (planet[p].texfname, "oberon.ppm");
  633.   planet[p].radius = 761.000000 / KM_TO_UNITS1;
  634.   planet[p].dist = 0.583000 / KM_TO_UNITS2;
  635.   planet[p].is_moon = 1;
  636.   planet[p].primary = 21;
  637.   planet[p].oblicity = 0.0;
  638.   planet[p].angvel = 0.004166 / 13.463;
  639.   p++;
  640.  
  641.   strcpy (planet[p].name, "Neptune");
  642.   strcpy (planet[p].texfname, "neptune.ppm");
  643.   planet[p].radius = 24766.000000 / KM_TO_UNITS1;
  644.   /* planet[p].dist = 449.8000000 / KM_TO_UNITS2; */
  645.   planet[p].dist = (realdistances ? 4498.0 : 125.0) / KM_TO_UNITS2;
  646.   planet[p].is_moon = 0;
  647.   planet[p].primary = 0;
  648.   planet[p].oblicity = 29.56;
  649.   planet[p].angvel = 0.004166 / 60189.0;
  650.   p++;
  651.  
  652.   strcpy (planet[p].name, "Triton");
  653.   strcpy (planet[p].texfname, "triton.ppm");
  654.   planet[p].radius = 1352.599976 / KM_TO_UNITS1;
  655.   planet[p].dist = 0.355000 / KM_TO_UNITS2;
  656.   planet[p].is_moon = 1;
  657.   planet[p].primary = 27;
  658.   planet[p].oblicity = 0.0;
  659.   planet[p].angvel = 0.004166 / -5.877;
  660.   p++;
  661.  
  662.   strcpy (planet[p].name, "Proteus");
  663.   strcpy (planet[p].texfname, "proteus.ppm");
  664.   planet[p].radius = 218.000000 / KM_TO_UNITS1;
  665.   planet[p].dist = 0.118000 / KM_TO_UNITS2;
  666.   planet[p].is_moon = 1;
  667.   planet[p].primary = 27;
  668.   planet[p].oblicity = 0.0;
  669.   planet[p].angvel = 0.004166 / 1.122;
  670.   p++;
  671.  
  672.   strcpy (planet[p].name, "Pluto");
  673.   strcpy (planet[p].texfname, "pluto.ppm");
  674.   planet[p].radius = 1137.000000 / KM_TO_UNITS1;
  675.   /* planet[p].dist = 590.6000000 / KM_TO_UNITS2; */
  676.   planet[p].dist = (realdistances ? 5906.0 : 150.0) / KM_TO_UNITS2;
  677.   planet[p].is_moon = 0;
  678.   planet[p].primary = 0;
  679.   planet[p].oblicity = 122.0;
  680.   planet[p].angvel = 0.004166 / 90465.0;
  681.   p++;
  682.  
  683.   strcpy (planet[p].name, "Charon");
  684.   strcpy (planet[p].texfname, "charon.ppm");
  685.   planet[p].radius = 586.000000 / KM_TO_UNITS1;
  686.   planet[p].dist = 0.019000 / KM_TO_UNITS2;
  687.   planet[p].is_moon = 1;
  688.   planet[p].primary = 30;
  689.   planet[p].oblicity = 0.0;
  690.   planet[p].angvel = 0.004166 / 6.387;
  691.   p++;
  692.  
  693.   /* Randomize planet positions */
  694.   PositionPlanets();
  695.  
  696.   /* Read textures, etc */
  697.   for (p=0; p<NPLANETS; p++)
  698.   {
  699.     if (planet[p].custom)
  700.     {
  701.       ReadPlanetTexture (p);
  702.       planet[p].custom = 0;
  703.     }
  704.  
  705.     planet[p].radius2 = planet[p].radius * planet[p].radius;
  706.     planet[p].hidden = 0;
  707.  
  708.     /* Set planet's mass */
  709.     planet[p].mass = planet[p].radius * planet[p].radius * planet[p].radius;
  710.   }
  711.  
  712.   /* Define planet display lists */
  713.   MakePlanetLists();
  714. }
  715.  
  716. void RandomPlanets()
  717. /*
  718.  *  Randomly set solar angle for each planet
  719.  */
  720. {
  721.   int p;
  722.  
  723.   Log ("RandomPlanets: Randomizing planets");
  724.  
  725.   for (p=0; p<NPLANETS; p++)
  726.   {
  727.     planet[p].theta = 2.0 * rnd (6.28);
  728.   }
  729. }
  730.  
  731. void PositionPlanets()
  732. /*
  733.  *  Turn planet angles into Cartesian coordinates
  734.  */
  735. {
  736.   int p, pr;
  737.   double th, v[3], v1[3];
  738.  
  739.   /* Position the planets */
  740.   for (p=0; p<NPLANETS; p++)
  741.   {
  742.     th = planet[p].theta;
  743.  
  744.     planet[p].pos[0] = planet[p].dist * sin (th);
  745.     planet[p].pos[1] = planet[p].dist * cos (th);
  746.     planet[p].pos[2] = 0.0;
  747.  
  748.     /* If moon, compute absolute position based on primary's
  749.      position and oblicity */
  750.     if (planet[p].is_moon)
  751.     {
  752.       pr = planet[p].primary;
  753.       th = -planet[pr].oblicity * 3.1415926535 / 180.0;
  754.       v[0] = 1.0;
  755.       v[1] = 0.0;
  756.       v[2] = 0.0;
  757.       RotateAbout (v1, planet[p].pos, v, th);
  758.       Vset (planet[p].pos, v1);
  759.       Vadd (planet[p].pos, planet[p].pos, planet[pr].pos);
  760.     }
  761.   }
  762. }
  763.  
  764. int InsidePlanet (double *v)
  765. /*
  766.  *  Check if v is inside a planet.  If yes, return planet
  767.  *  index, else -1
  768.  */
  769. {
  770.   int p;
  771.   double v1[3], r2;
  772.  
  773.   for (p=0; p<NPLANETS; p++)
  774.   {
  775.     if (!planet[p].hidden)
  776.     {
  777.       Vsub (v1, v, planet[p].pos);
  778.       r2 = Mag2 (v1);
  779.  
  780.       /* Inside? */
  781.       if (r2 < planet[p].radius2)
  782.       {
  783.         /* Yep */
  784.         return (p);
  785.       }
  786.     }
  787.   }
  788.  
  789.   /* Nope */
  790.   return (-1);
  791. }
  792.  
  793. void ShowPlanetNames()
  794. {
  795.   int p;
  796.   unsigned char v;
  797.   double v1[3]; 
  798.   char buf[128];
  799.  
  800.   for (p=0; p<NPLANETS; p++)
  801.   {
  802.     if (!planet[p].hidden)
  803.     {
  804.       if (planet[p].is_moon)
  805.       glColor3d (0.0, 0.8, 0.8);
  806.       else
  807.       glColor3d (0.0, 0.0, 0.8);
  808.  
  809.       Vsub (v1, planet[p].pos, player.pos);
  810.       glRasterPos3dv (v1);
  811.       glGetBooleanv (GL_CURRENT_RASTER_POSITION_VALID, &v);
  812.       if (v)
  813.       {
  814.         if (!planet[p].is_moon)
  815.         {
  816.           if (planet[p].absrange2 < 100.0*planet[p].radius*planet[p].radius) 
  817.           {
  818.             sprintf (buf, "%s:%.0lf", planet[p].name, 
  819.             KM_TO_UNITS1*(sqrt(planet[p].absrange2)-planet[p].radius)); 
  820.           }
  821.           else 
  822.           {
  823.             strcpy (buf, planet[p].name); 
  824.           }
  825.           Print (GLUT_BITMAP_HELVETICA_10, buf);
  826.         }
  827.         else
  828.         {
  829.           if (planet[p].range2 < (2000.0 * 2000.0))
  830.           {
  831.             if (planet[p].absrange2 < 100.0*planet[p].radius*planet[p].radius) 
  832.             {
  833.               sprintf (buf, "%s:%.0lf", planet[p].name, 
  834.               KM_TO_UNITS1*(sqrt(planet[p].absrange2)-planet[p].radius)); 
  835.             }
  836.             else 
  837.             {
  838.               strcpy (buf, planet[p].name); 
  839.             }
  840.             Print (GLUT_BITMAP_HELVETICA_10, buf);
  841.           }
  842.         }
  843.       }
  844.     }
  845.   }
  846. }
  847.  
  848. void Sphere (double r, int slices, int sectors)
  849. {
  850.   GLUquadricObj *obj;
  851.  
  852.   obj = gluNewQuadric();
  853.   
  854.   gluQuadricDrawStyle (obj, GLU_FILL);
  855.   gluQuadricNormals (obj, GLU_SMOOTH);
  856.   gluQuadricTexture (obj, GL_TRUE);
  857.   gluSphere (obj, (float)r, sectors, slices);
  858. }
  859.  
  860. int FindPlanetByName (char *c)
  861. /*
  862.  *  Find planet given name, else -1
  863.  */
  864. {
  865.   int p;
  866.  
  867.   for (p=0; p<NPLANETS; p++)
  868.   {
  869.     if (!strcasecmp (c, planet[p].name)) return (p);
  870.   }
  871.  
  872.   return (-1);
  873. }
  874.  
  875. void MakeOrbitLists()
  876. /*
  877.  *  Construct display lists for orbits
  878.  */
  879. {
  880.   int p;
  881.   double th, d, s, c;
  882.  
  883.   d = 360.0 / ((double) ORBIT_SECTORS);
  884.  
  885.   /* Loop through planets */
  886.   for (p=1; p<NPLANETS; p++)
  887.   {
  888.     /* Delete old list */
  889.     if (glIsList (planet[p].orbitlist)) glDeleteLists (planet[p].orbitlist, 1);
  890.  
  891.     /* Make new list */
  892.     planet[p].orbitlist = glGenLists (1);
  893.     glNewList (planet[p].orbitlist, GL_COMPILE);
  894.  
  895.     glBegin (GL_LINE_LOOP);
  896.  
  897.     /* Set color */
  898.     if (planet[p].is_moon)
  899.     {
  900.       glColor3f (0.0, 0.8, 0.8);
  901.     }
  902.     else
  903.     {
  904.       glColor3f (0.0, 0.0, 1.0);
  905.     }
  906.  
  907.     /* Loop through circle */
  908.     for (th=0.0; th<360.0; th+=d)
  909.     {
  910.       s = sin (th*3.1415926535/180.0);
  911.       c = cos (th*3.1415926535/180.0);
  912.  
  913.       glVertex3d (planet[p].dist*s, planet[p].dist*c, 0.0);
  914.     }
  915.  
  916.     glEnd();
  917.     glEndList();
  918.   }
  919. }
  920.  
  921. void DrawOrbits()
  922. /*
  923.  *  Draw orbital paths
  924.  */
  925. {
  926.   int p;
  927.   double v[3];
  928.  
  929.   glDisable (GL_TEXTURE_2D);
  930.   glDisable (GL_LIGHTING);
  931.  
  932.   glPushMatrix();
  933.   Vsub (v, planet[0].pos, player.pos);
  934.   glTranslated (v[0], v[1], v[2]);
  935.  
  936.   for (p=1; p<NPLANETS; p++)
  937.   {
  938.     if (!planet[p].hidden)
  939.     {
  940.       if (planet[p].is_moon)
  941.       {
  942.         if (planet[planet[p].primary].range2 > 200.0*200.0) continue;
  943.  
  944.         glPushMatrix();
  945.         Vsub (v, player.pos, planet[0].pos);
  946.         glTranslated (v[0], v[1], v[2]);
  947.  
  948.         Vsub (v, planet[planet[p].primary].pos, player.pos);
  949.         glTranslated (v[0], v[1], v[2]);
  950.  
  951.         glRotated (planet[planet[p].primary].oblicity, 1.0, 0.0, 0.0);
  952.       }
  953.       glCallList (planet[p].orbitlist);
  954.       if (planet[p].is_moon) glPopMatrix();
  955.     }
  956.   }
  957.  
  958.   glPopMatrix();
  959. }
  960.  
  961. void MovePlanets()
  962. /*
  963.  *  Move planets in their orbits
  964.  */
  965. {
  966.   int p;
  967.  
  968.   for (p=1; p<NPLANETS; p++)
  969.   {
  970.     planet[p].theta -= planet[p].angvel * deltaT * compression 
  971.     * 3.1415926535 / 180.0; 
  972.     if (planet[p].theta < 0.0) planet[p].theta += 2.0 * 3.1415926535; 
  973.   }
  974.  
  975.   PositionPlanets();
  976. }
  977.